package 代码随想录.链表;

public class _3设计链表 {
    /**
     * 707. 设计链表
     * https://leetcode.cn/problems/design-linked-list/
     * 你可以选择使用单链表或者双链表，设计并实现自己的链表。
     */
    class ListNode2{
        int val;
        ListNode2 next;
        ListNode2(){}
        ListNode2(int val){
            this.val = val;
        }
        ListNode2(int val,ListNode2 next){
            this.val = val;
            this.next = next;
        }
    }
    class MyLinkedList {

        //size存储链表元素的个数
        int size;
        //虚拟头结点
        ListNode2 head;

        public MyLinkedList() {
            size = 0;
            head = new ListNode2(0);
        }

        public int get(int index) {
            //如果index非法，返回-1
            if (index < 0 || index >= size) {
                return -1;
            }
            ListNode2 currentNode = head;
            //包含一个虚拟头节点，所以查找第 index+1 个节点
            for (int i = 0; i <= index; i++) {
                currentNode = currentNode.next;
            }
            return currentNode.val;
        }

        public void addAtHead(int val) {
            addAtIndex(0, val);
        }

        public void addAtTail(int val) {
            addAtIndex(size, val);
        }

        public void addAtIndex(int index, int val) {
            if (index > size) {
                return;
            }
            if (index < 0) {
                index = 0;
            }
            size++;
            //找到要插入节点的前驱
            ListNode2 pred = head;
            for (int i = 0; i < index; i++) {
                pred = pred.next;
            }
            ListNode2 toAdd = new ListNode2(val);
            toAdd.next = pred.next;
            pred.next = toAdd;
        }

        public void deleteAtIndex(int index) {
            if (index < 0 || index >= size) {
                return;
            }
            size--;
            if (index == 0) {
                head = head.next;
                return;
            }
            ListNode2 pred = head;
            for (int i = 0; i < index ; i++) {
                pred = pred.next;
            }
            pred.next = pred.next.next;
        }
    }

    //双链表
    class ListNode{
        int val;
        ListNode next,prev;
        ListNode() {};
        ListNode(int val){
            this.val = val;
        }
    }

    class MyLinkedList2 {

        //记录链表中元素的数量
        int size;
        //记录链表的虚拟头结点和尾结点
        ListNode head,tail;

        public MyLinkedList2() {
            //初始化操作
            this.size = 0;
            this.head = new ListNode(0);
            this.tail = new ListNode(0);
            //这一步非常关键，否则在加入头结点的操作中会出现null.next的错误！！！
            head.next=tail;
            tail.prev=head;
        }

        public int get(int index) {
            //判断index是否有效
            if(index<0 || index>=size){
                return -1;
            }
            ListNode cur = this.head;
            //判断是哪一边遍历时间更短
            if(index >= size / 2){
                //tail开始
                cur = tail;
                for(int i=0; i< size-index; i++){
                    cur = cur.prev;
                }
            }else{
                for(int i=0; i<= index; i++){
                    cur = cur.next;
                }
            }
            return cur.val;
        }

        public void addAtHead(int val) {
            //等价于在第0个元素前添加
            addAtIndex(0,val);
        }

        public void addAtTail(int val) {
            //等价于在最后一个元素(null)前添加
            addAtIndex(size,val);
        }

        public void addAtIndex(int index, int val) {
            //index大于链表长度
            if(index>size){
                return;
            }
            //index小于0
            if(index<0){
                index = 0;
            }
            size++;
            //找到前驱
            ListNode pre = this.head;
            for(int i=0; i<index; i++){
                pre = pre.next;
            }
            //新建结点
            ListNode newNode = new ListNode(val);
            newNode.next = pre.next;
            pre.next.prev = newNode;
            newNode.prev = pre;
            pre.next = newNode;

        }

        public void deleteAtIndex(int index) {
            //判断索引是否有效
            if(index<0 || index>=size){
                return;
            }
            //删除操作
            size--;
            ListNode pre = this.head;
            for(int i=0; i<index; i++){
                pre = pre.next;
            }
            pre.next.next.prev = pre;
            pre.next = pre.next.next;
        }
    }

}
